/*
 * Copyright (c) GoKeep by gokeep.org. 2022-2023. All rights reserved
 */
package org.gokeep.communication.service.impl;

import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.gokeep.common.config.properties.SystemConfigProperties;
import org.gokeep.common.document.*;
import org.gokeep.common.dto.FriendBaseDto;
import org.gokeep.common.dto.FriendDto;
import org.gokeep.common.dto.UserDetailDto;
import org.gokeep.common.dto.UserRegisterDto;
import org.gokeep.common.exception.GoKeepException;
import org.gokeep.common.mapper.UserMapper;
import org.gokeep.common.repository.*;
import org.gokeep.communication.service.UserService;
import org.mindrot.jbcrypt.BCrypt;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;

@Slf4j
@Service
public class UserServiceImpl implements UserService {

    @Resource
    private UserRepository userRepository;

    @Resource
    private UserExtendRepository userExtendRepository;

    @Resource
    private CompanyRepository companyRepository;

    @Resource
    private SystemConfigProperties systemConfigProperties;

    @Resource
    private OrganizationRepository organizationRepository;

    @Resource
    private GroupRepository groupRepository;

    @Resource
    private UserFriendsRepository userFriendsRepository;

    @Resource
    private UserMapper userMapper;

    /**
     * 创建用户，主要用于添加用户
     *
     * @param user
     */
    @Override
    @Transactional
    public void createUser(User user) {
        if (user.getUsername() == null) throw new AssertionError("username is null");
        if (user.getPassword() == null) throw new AssertionError("password is null");
        String password = user.getPassword();
        user.setOpenId(RandomStringUtils.random(32));
        user.setPassword(BCrypt.hashpw(password, BCrypt.gensalt()));
        UserExtend userExtend = new UserExtend();
        user.setExtend(userExtend);
        userRepository.save(user);
    }

    @Override
    public User getUserById(String userId) {
        return userRepository.findById(userId).orElse(null);
    }

    @Override
    public User getUserByUsername(String username) {
        return userRepository.findByUsername(username).orElse(null);
    }

    @Override
    public FriendDto getUserFriends(String userId) {
        FriendDto dto = new FriendDto();
        // 获取当前用户信息
        Optional<User> userOptional = userRepository.findById(userId);
        assert userOptional.isPresent() : new GoKeepException("Current user is invalid user, cause is not found user");
        String companyId = userOptional.get().getCompanyId();
        // 设置企业用户信息
        if (StringUtils.isNotBlank(companyId)) {
            List<User> users = userRepository.findByCompanyId(companyId);
            dto.setCompanyFriends(getFriendsBaseFromUsers(userId, users));
        }
        // 设置企业外用户（普通好友关系用户）信息
        Optional<UserFriends> userFriendsOptional = userFriendsRepository.findById(userId);
        if (userFriendsOptional.isPresent()) {
            UserFriends userFriends = userFriendsOptional.get();
            List<String> friendUserIds = userFriends.getFriendUserIds();
            List<User> users = getUserByUserIds(friendUserIds);
            if (!CollectionUtils.isEmpty(users)) {
                dto.setFriends(getFriendsBaseFromUsers(userId, users));
            }
        }
        return dto;
    }

    /**
     * 通过用户列表转换为好友DTO对象
     *
     * @param users
     * @return
     */
    public List<FriendBaseDto> getFriendsBaseFromUsers(String currentUserId, List<User> users) {
        return users.stream()
                .filter(user1 -> !user1.getUserId().equals(currentUserId))
                .map(userMapper::toDto)
                .toList();
    }

    /**
     * 根据userID，userList获取单个用户信息
     * 这里的遍历不能改为lambda表达式方式，性能反而下降
     *
     * @param users
     * @param userId
     * @return
     */
    public User findUserByUserList(List<User> users, String userId) {
        if (CollectionUtils.isEmpty(users)) {
            return null;
        }
        for (User user : users) {
            if (user.getUserId().equals(userId)) {
                return user;
            }
        }
        return null;
    }

    /**
     * 根据userIds获取用户列表
     *
     * @param userIds
     * @return
     */
    public List<User> getUserByUserIds(List<String> userIds) {
        return userRepository.findAllById(userIds);
    }

    /**
     * 获取用户详情
     *
     * @param userId
     * @return
     */
    @Override
    public UserDetailDto detail(String userId) {
        User user = getUserById(userId);
        if (Objects.isNull(user)) {
            return null;
        }
        UserDetailDto dto = userMapper.toDetailDto(user);
        UserExtend extend = user.getExtend();
        if (!Objects.isNull(extend)) {
            dto.setRemark(extend.getRemark());
        }
        String companyId = user.getCompanyId();
        if (StringUtils.isNotBlank(companyId)) {
            Optional<Company> optional = companyRepository.findById(companyId);
            optional.ifPresent(company -> dto.setCompanyName(company.getName()));
        }
        return dto;
    }

    /**
     * 开放模式下用户注册接口
     *
     * @param userRegister
     */
    @Override
    public void registerUser(UserRegisterDto userRegister) {
        // TODO: 注册用户需要手机短信验证码，需要花钱，怎么办？？？，邮箱不花钱，但是不方便，可以考虑微信第三方登录
        User user = userMapper.toEntity(userRegister);
        userRepository.save(user);
    }

    @Override
    public FriendDto getGroupMemberUser(String groupId) {
        Optional<Group> optional = groupRepository.findById(groupId);
        if (optional.isPresent()) {
            Group group = optional.get();
            List<GroupMember> groupMember = group.getGroupMembers();

            return null;
        }
        return null;
    }

    /**
     * 获取某一个用户的扩展信息
     *
     * @param companies
     * @param companyId
     * @return
     */
    private Company getCompanyByUserId(List<Company> companies, String companyId) {
        return companies.stream().filter(company -> company.getCompanyId().equals(companyId)).findFirst().orElse(null);
    }
}